home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / exec / allocabs.c < prev    next >
C/C++ Source or Header  |  1996-09-13  |  4KB  |  163 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: allocabs.c,v 1.5 1996/09/13 17:51:21 digulla Exp $
  4.     $Log: allocabs.c,v $
  5.     Revision 1.5  1996/09/13 17:51:21  digulla
  6.     Use IPTR
  7.  
  8.     Revision 1.4  1996/08/13 13:55:57  digulla
  9.     Replaced __AROS_LA by __AROS_LHA
  10.     Replaced some __AROS_LH*I by __AROS_LH*
  11.     Sorted and added includes
  12.  
  13.     Revision 1.3  1996/08/01 17:41:04  digulla
  14.     Added standard header for all files
  15.  
  16.     Desc:
  17.     Lang:
  18. */
  19. #include <exec/memory.h>
  20. #include <exec/alerts.h>
  21. #include <exec/execbase.h>
  22. #include "machine.h"
  23. #include "memory.h"
  24.  
  25. /*****************************************************************************
  26.  
  27.     NAME */
  28.     #include <clib/exec_protos.h>
  29.  
  30.     __AROS_LH2(APTR, AllocAbs,
  31.  
  32. /*  SYNOPSIS */
  33.     __AROS_LHA(ULONG, byteSize, D0),
  34.     __AROS_LHA(APTR,  location, D1),
  35.  
  36. /*  LOCATION */
  37.     struct ExecBase *, SysBase, 34, Exec)
  38.  
  39. /*  FUNCTION
  40.     Allocate some memory from the system memory pool at a given address.
  41.  
  42.     INPUTS
  43.     byteSize - Number of bytes you want to get
  44.     location - Where you want to get the memory
  45.  
  46.     RESULT
  47.     A pointer to some memory including the requested bytes or NULL if
  48.     the memory couldn't be allocated
  49.  
  50.     NOTES
  51.  
  52.     EXAMPLE
  53.  
  54.     BUGS
  55.  
  56.     SEE ALSO
  57.     FreeMem()
  58.  
  59.     INTERNALS
  60.  
  61.     HISTORY
  62.        17-10-95    created by M. Fleischer
  63.  
  64. ******************************************************************************/
  65. {
  66.     __AROS_FUNC_INIT
  67.     struct MemChunk *p1,*p2,*p3,*p4;
  68.     struct MemHeader *mh;
  69.  
  70.     /* Zero bytes requested? May return everything ;-). */
  71.     if(!byteSize)
  72.     return NULL;
  73.  
  74.     /* Align size to the requirements */
  75.     byteSize+=(IPTR)location&(MEMCHUNK_TOTAL-1);
  76.     byteSize=(byteSize+MEMCHUNK_TOTAL-1)&~(MEMCHUNK_TOTAL-1);
  77.  
  78.     /* Align the location as well */
  79.     location=(APTR)((IPTR)location&~(MEMCHUNK_TOTAL-1));
  80.  
  81.     /* Start and end(+1) of the block */
  82.     p3=(struct MemChunk *)location;
  83.     p4=(struct MemChunk *)((UBYTE *)p3+byteSize);
  84.  
  85.     /* Protect the memory list from access by other tasks. */
  86.     Forbid();
  87.  
  88.     /* Loop over MemHeader structures */
  89.     mh=(struct MemHeader *)SysBase->MemList.lh_Head;
  90.     while(mh->mh_Node.ln_Succ)
  91.     {
  92.     /* Test if the memory belongs to this MemHeader. */
  93.     if(mh->mh_Lower<=location&&mh->mh_Upper>location)
  94.     {
  95.         /*
  96.         The free memory list is only single linked, i.e. to remove
  97.         elements from the list I need the node's predessor. For the
  98.         first element I can use freeList->mh_First instead of a real
  99.         predessor.
  100.         */
  101.         p1=(struct MemChunk *)&mh->mh_First;
  102.         p2=p1->mc_Next;
  103.  
  104.         /* Follow the list to find a chunk with our memory. */
  105.         while(p2!=NULL)
  106.         {
  107. #if !defined(NO_CONSISTENCY_CHECKS)
  108.         /*
  109.             Do some constistency checks:
  110.             1. All MemChunks must be aligned to
  111.                MEMCHUNK_TOTAL.
  112.             2. The end (+1) of the current MemChunk
  113.                must be lower than the start of the next one.
  114.         */
  115.         if(  ((IPTR)p2|p2->mc_Bytes)&(MEMCHUNK_TOTAL-1)
  116.             ||(  (UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p2->mc_Next
  117.             &&p2->mc_Next!=NULL))
  118.             Alert(AN_MemCorrupt|AT_DeadEnd);
  119. #endif
  120.         /* Found a chunk that fits? */
  121.         if((UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p4&&p2<=p3)
  122.         {
  123.             /* Check if there's memory left at the end. */
  124.             if((UBYTE *)p2+p2->mc_Bytes!=(UBYTE *)p4)
  125.             {
  126.             /* Yes. Add it to the list */
  127.             p4->mc_Next=p2->mc_Next;
  128.             p4->mc_Bytes=(UBYTE *)p2+p2->mc_Bytes-(UBYTE *)p4;
  129.             p2->mc_Next=p4;
  130.             }
  131.  
  132.             /* Check if there's memory left at the start. */
  133.             if(p2!=p3)
  134.             /* Yes. Adjust the size */
  135.             p2->mc_Bytes=(UBYTE *)p3-(UBYTE *)p2;
  136.             else
  137.             /* No. Skip the old chunk */
  138.             p1->mc_Next=p2->mc_Next;
  139.  
  140.             /* Adjust free memory count */
  141.             mh->mh_Free-=byteSize;
  142.  
  143.             /* Return the memory */
  144.             Permit();
  145.             return p3;
  146.         }
  147.         /* goto next chunk */
  148.         p1=p2;
  149.         p2=p2->mc_Next;
  150.         }
  151.         /* The MemHeader didn't have the memory */
  152.         break;
  153.     }
  154.     /* Test next MemHeader */
  155.     mh=(struct MemHeader *)mh->mh_Node.ln_Succ;
  156.     }
  157.     /* There's nothing we could do */
  158.     Permit();
  159.     return NULL;
  160.     __AROS_FUNC_EXIT
  161. } /* AllocAbs */
  162.  
  163.